/*
 * @Copyright: 2017 www.yyfax.com Inc. All rights reserved.
 */
package com.yyfax.pay.order.service;

import java.net.InetAddress;
import java.util.List;

import com.yyfax.framework.common.Log;
import com.yyfax.pay.common.util.RequestUtil;
import com.yyfax.pay.order.model.to.AuthWithoutVerifyParams;
import com.yyfax.pay.order.model.to.auth.AuthWithoutVerifyDirectParams;
import com.yyfax.pay.third.model.to.yyfax.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;

import com.yyfax.commons.http.HttpUtil;
import com.yyfax.commons.json.JacksonUtil;
import com.yyfax.commons.lang.DateUtil;
import com.yyfax.framework.exception.YYException;
import com.yyfax.framework.yyfax.CryptUtil;
import com.yyfax.framework.yyfax.DesensitizationUtil;
import com.yyfax.framework.yyfax.enums.IdCardTypeEnum;
import com.yyfax.framework.yyfax.enums.UserTypeEnum;
import com.yyfax.framework.yyfax.enums.YesNoEnum;
import com.yyfax.pay.common.constants.PayConstants;
import com.yyfax.pay.common.enums.AuthStateEnum;
import com.yyfax.pay.common.enums.NotifyTaskTypeEnum;
import com.yyfax.pay.common.enums.PayModeEnum;
import com.yyfax.pay.common.enums.PayRspCodeEnum;
import com.yyfax.pay.common.enums.PayTypeEnum;
import com.yyfax.pay.common.enums.PaymentEnum;
import com.yyfax.pay.common.exception.YYPayException;
import com.yyfax.pay.common.util.QuotaUtil;
import com.yyfax.pay.config.data.service.MerchantConfigService;
import com.yyfax.pay.config.data.service.MerchantPaymentService;
import com.yyfax.pay.config.data.service.PaymentQuotaService;
import com.yyfax.pay.config.model.po.MerchantConfigPO;
import com.yyfax.pay.config.model.po.MerchantPaymentPO;
import com.yyfax.pay.config.model.po.PaymentQuotaPO;
import com.yyfax.pay.order.data.service.AuthOrderService;
import com.yyfax.pay.order.data.service.UserAuthService;
import com.yyfax.pay.order.data.service.UserPaymentService;
import com.yyfax.pay.order.model.po.AuthOrderPO;
import com.yyfax.pay.order.model.po.NotifyTaskPO;
import com.yyfax.pay.order.model.po.UserAuthPO;
import com.yyfax.pay.order.model.po.UserPaymentPO;
import com.yyfax.pay.order.model.to.AuthCounterSignParams;
import com.yyfax.pay.order.model.to.AuthOrderParams;
import com.yyfax.pay.order.model.to.AuthResultNotifyParams;
import com.yyfax.pay.order.model.to.AuthResultNotifyParams.AuthNotifyParams;
import com.yyfax.pay.order.model.to.user.UserBankInfoContent;
import com.yyfax.pay.order.model.vo.UserAuthVO;
import com.yyfax.pay.order.model.vo.UserPaymentVO;
import com.yyfax.pay.third.service.ThirdPayService;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * 用户鉴权信息服务
 *
 * @author buyi
 * @date 2017-04-20 21:20:00
 * @since v1.0.0
 */
@Service
public class AuthService {
	private Logger logger = LoggerFactory.getLogger(getClass());

	@Autowired
	private AuthOrderService authOrderService;

	@Autowired
	private AdapterService adapterService;

	@Autowired
	private UserAuthService userAuthService;

	@Autowired
	private MerchantConfigService merchantConfigService;

	@Autowired
	private PayCommonService payCommonService;

	@Autowired
	private RouteService routeService;

	@Autowired
	private UserPaymentService userPaymentService;

	@Autowired
	private MerchantPaymentService merchantPaymentService;

	@Autowired
	private PaymentQuotaService paymentQuotaService;

	@Autowired
	private PayConstants payConstants;

	/**
	 * 获取用户优先支付认证信息
	 *
	 * @param merchantCode
	 * @param userId
	 * @return
	 * @throws Exception
	 * @author buyi
	 * @date 2017-05-04 11:50:22
	 * @since v1.0.0
	 */
	public UserBankInfoContent queryDefaultUserPayment(String merchantCode, String userId) throws Exception {
		UserAuthVO userAuthVO = userAuthService.queryUserAuthVO(merchantCode, userId);
		if (userAuthVO == null || userAuthVO.getUserPaymentVOs().isEmpty()) {
			return null;
		}

		List<MerchantPaymentPO> merchantPaymentPOs = merchantPaymentService.queryList(merchantCode, PayTypeEnum.PAY.getValue());

		UserPaymentVO userPaymentVO = userAuthVO.getUserPayment(merchantPaymentPOs);

		UserBankInfoContent content = new UserBankInfoContent();
		if (userPaymentVO != null) {
			content.setBankEnName(userPaymentVO.getBankEnName());
			content.setBankName(userPaymentVO.getBankName());

			// 兼容富友存管版本，新增主体类型、支付类型,edit by yuch since 2.0.0
			// PaymentQuotaPO paymentQuotaPO = paymentQuotaService.query(merchantCode, userPaymentVO.getPaymentCode(),
			PaymentQuotaPO paymentQuotaPO = paymentQuotaService.query(merchantCode, userPaymentVO.getPaymentCode(), userPaymentVO.getBankCode(),
					UserTypeEnum.NATURAL_PERSON.getValue(), PayModeEnum.AUTH_PAY.getValue());
			if (paymentQuotaPO == null) {
				throw new YYPayException(PayRspCodeEnum.PAY_CODE_MERCHANT_CONFIG_ILLEGAL, "商户：" + merchantCode + "限额配置信息payment_quota缺失", "商户配置信息异常");
			}

			content.setSingleQuota(QuotaUtil.covertToCN(paymentQuotaPO.getSingleQuota(), 0));
			content.setDayQuota(QuotaUtil.covertToCN(paymentQuotaPO.getDayQuota(), 0));
			content.setMonthQuota(QuotaUtil.covertToCN(paymentQuotaPO.getMonthQuota(), 0));

			String cardNo = CryptUtil.decrypt(userPaymentVO.getCardNoCip());
			content.setTailCardNo(cardNo.substring(cardNo.length() - 4));
			content.setRemark(paymentQuotaPO.getRemark());
		}

		return content;
	}

	/**
	 * 发送独立鉴权验证码
	 *
	 * @param params
	 * @return
	 * @throws Throwable
	 * @author buyi
	 * @date 2017-04-24 16:06:59
	 * @since v1.0.0
	 */
	// public SendAuthenticationVerifyCodeYYContent
	// sendVerifyCode(AuthCounterSignParams params) throws Throwable {
	//
	// // 获取订单信息
	// AuthOrderPO authOrderPO =
	// authOrderService.queryByOrderIdAndMerchantCode(params.getOrderId(),
	// params.getMerchantCode());
	// if (authOrderPO == null) {
	// throw new YYException(PayRspCodeEnum.COMMON_ERROR_OBJECT_NOT_FOUND,
	// "鉴权订单不存在", "鉴权订单不存在");
	// }
	//
	// ThirdPayService adapterPayService =
	// adapterService.adapterPayService(PaymentEnum.fromValue(params.getPaymentCode()));
	//
	// String idNo = StringUtils.isBlank(authOrderPO.getIdNoCip()) ?
	// params.getIdNo() : CryptUtil.decrypt(authOrderPO.getIdNoCip());
	// String name = StringUtils.isBlank(authOrderPO.getName()) ?
	// params.getName() : authOrderPO.getName();
	// String cardNo = StringUtils.isBlank(authOrderPO.getCardNoCip()) ?
	// params.getCardNo() : CryptUtil.decrypt(authOrderPO.getCardNoCip());
	//
	// // 封装发送验证码实体
	// SendAuthenticationVerifyCodeYYParams sendVerifyCodeParams = new
	// SendAuthenticationVerifyCodeYYParams();
	// BeanUtils.copyProperties(authOrderPO, sendVerifyCodeParams);
	// sendVerifyCodeParams.setIdNo(idNo);
	// sendVerifyCodeParams.setName(name);
	// sendVerifyCodeParams.setCardNo(cardNo);
	// sendVerifyCodeParams.setPhone(params.getPhone());
	//
	// SendAuthenticationVerifyCodeYYContent sendVerifyCodeYYContent =
	// adapterPayService.sendAuthenticationVerifyCode(sendVerifyCodeParams);
	//
	// if (sendVerifyCodeYYContent == null) {
	// throw new YYException(PayRspCodeEnum.PAY_CODE_GET_AUTH_VERIFY_CODE_FAIL,
	// "鉴权响应为空", "鉴权响应为空");
	// }
	//
	// return sendVerifyCodeYYContent;
	// }
	public SendAuthenticationVerifyCodeYYContent sendVerifyCode(AuthOrderPO authOrderPO, String idNo, String name, String cardNo, String phone)
			throws Throwable {
		// 获取订单信息
		if (authOrderPO == null) {
			throw new YYException(PayRspCodeEnum.COMMON_ERROR_OBJECT_NOT_FOUND, "鉴权订单不存在", "鉴权订单不存在");
		}

		ThirdPayService adapterPayService = adapterService.adapterPayService(PaymentEnum.fromValue(authOrderPO.getActPaymentCode()));

		String actIdNo = StringUtils.isBlank(authOrderPO.getIdNoCip()) ? idNo : CryptUtil.decrypt(authOrderPO.getIdNoCip());
		String actName = StringUtils.isBlank(authOrderPO.getName()) ? name : authOrderPO.getName();
		String actcardNo = StringUtils.isBlank(authOrderPO.getCardNoCip()) ? cardNo : CryptUtil.decrypt(authOrderPO.getCardNoCip());

		// 封装发送验证码实体
		SendAuthenticationVerifyCodeYYParams sendVerifyCodeParams = new SendAuthenticationVerifyCodeYYParams();
		BeanUtils.copyProperties(authOrderPO, sendVerifyCodeParams);
		sendVerifyCodeParams.setIdNo(actIdNo);
		sendVerifyCodeParams.setName(actName);
		sendVerifyCodeParams.setCardNo(actcardNo);
		sendVerifyCodeParams.setPhone(phone);

		SendAuthenticationVerifyCodeYYContent sendVerifyCodeYYContent = adapterPayService.sendAuthenticationVerifyCode(sendVerifyCodeParams);

		if (sendVerifyCodeYYContent == null) {
			throw new YYException(PayRspCodeEnum.PAY_CODE_GET_AUTH_VERIFY_CODE_FAIL, "鉴权响应为空", "鉴权响应为空");
		}

		return sendVerifyCodeYYContent;
	}

	public AuthenticationYYContent authentication(AuthOrderPO authOrderPO, String idNo, String name, String cardNo, String phone, String token,
			String validCode) throws Throwable {

		String actIdNo = StringUtils.isBlank(authOrderPO.getIdNoCip()) ? idNo : CryptUtil.decrypt(authOrderPO.getIdNoCip());
		String actName = StringUtils.isBlank(authOrderPO.getName()) ? name : authOrderPO.getName();
		String actCardNo = StringUtils.isBlank(authOrderPO.getCardNoCip()) ? cardNo : CryptUtil.decrypt(authOrderPO.getCardNoCip());

		// 判断鉴权信息是否被占用
		userAuthService.checkIdNoAndName(authOrderPO.getMerchantCode(), authOrderPO.getUserId(), idNo, name);

		ThirdPayService adapterPayService = adapterService.adapterPayService(PaymentEnum.fromValue(authOrderPO.getActPaymentCode()));

		AuthenticationYYParams authenticationYYParams = new AuthenticationYYParams();
		BeanUtils.copyProperties(authOrderPO, authenticationYYParams);
		authenticationYYParams.setToken(token);
		authenticationYYParams.setValidCode(validCode);
		authenticationYYParams.setPhone(phone);
		authenticationYYParams.setIdNo(actIdNo);
		authenticationYYParams.setName(actName);
		authenticationYYParams.setCardNo(actCardNo);

		AuthenticationYYContent authenticationYYContent = adapterPayService.authentication(authenticationYYParams);
		if (authenticationYYContent == null) {
			throw new YYException(PayRspCodeEnum.PAY_CODE_GET_AUTH_VERIFY_CODE_FAIL, "鉴权响应为空", "鉴权响应为空");
		}

		// 如果不是订单状态不是成功
		if (!PayRspCodeEnum.SUCCESS.isValue(authenticationYYContent.getResultCode())) {
			throw new YYException(authenticationYYContent.getResultCode(), authenticationYYContent.getResultMsg(),
					authenticationYYContent.getResultMsg());
		}

		// 鉴权成功,更新鉴权订单信息
		authOrderPO.setIdNo(DesensitizationUtil.convertIdCard(idNo));
		authOrderPO.setIdNoCip(CryptUtil.encrypt(idNo));
		authOrderPO.setIdType(IdCardTypeEnum.PRC_ID.getValue());
		authOrderPO.setName(name);
		authOrderPO.setCardNo(DesensitizationUtil.convertIdCard(cardNo));
		authOrderPO.setCardNoCip(CryptUtil.encrypt(cardNo));
		authOrderPO.setState(AuthStateEnum.SUCCESS.getValue());
		authOrderPO.setPhone(phone);

		authOrderService.modify(authOrderPO);

		// 保存用户鉴权信息
		saveUserAuthAndUserPayment(authOrderPO.getMerchantCode(), authOrderPO.getUserId(), idNo, name, authOrderPO.getActPaymentCode(), cardNo,
				phone);

		// 生成异步通知任务
		saveNotifyTask(authenticationYYContent, authOrderPO);

		return authenticationYYContent;
	}

	/**
	 * 鉴权信息校验
	 *
	 * @param authOrderPO
	 * @return
	 * @author xulqb
	 * @date 2017/12/21 14:35
	 * @since V1.0.0
	 */
	public WithoutVerifyYYContent authentication(AuthOrderPO authOrderPO, AuthWithoutVerifyDirectParams params) throws Throwable {

		String actIdNo = CryptUtil.decrypt(authOrderPO.getIdNoCip());
		String actName = authOrderPO.getName();
		String actCardNo = CryptUtil.decrypt(authOrderPO.getCardNoCip());

		ThirdPayService adapterPayService = adapterService.adapterPayService(PaymentEnum.fromValue(authOrderPO.getPaymentCode()));

		WithoutVerifyYYParams authenticationYYParams = new WithoutVerifyYYParams();
		BeanUtils.copyProperties(authOrderPO, authenticationYYParams);
		authenticationYYParams.setPhone(authOrderPO.getPhone());
		authenticationYYParams.setIdNo(actIdNo);
		authenticationYYParams.setName(actName);
		authenticationYYParams.setCardNo(actCardNo);

		WithoutVerifyYYContent withoutVerifyYYContent = adapterPayService.authenticationWithout(authenticationYYParams);
		if (withoutVerifyYYContent == null) {
			throw new YYException(PayRspCodeEnum.PAY_CODE_GET_AUTH_VERIFY_CODE_FAIL, "鉴权响应为空", "鉴权响应为空");
		}

		String state = AuthStateEnum.FAIL.getValue();
		if (PayRspCodeEnum.SUCCESS.isValue(withoutVerifyYYContent.getResultCode())) {
			state = AuthStateEnum.SUCCESS.getValue();
		} else if (PayRspCodeEnum.PAY_CODE_REQ_TIME_OUT.isValue(withoutVerifyYYContent.getResultCode())) {
			// 如果是超时，则更新成处理中
			state = AuthStateEnum.DEALING.getValue();
		}

		// 更新鉴权订单信息
		authOrderPO.setState(state);
		authOrderPO.setResultCode(withoutVerifyYYContent.getResultCode());
		authOrderPO.setResultMsg(withoutVerifyYYContent.getResultMsg());
		authOrderPO.setPhone(authOrderPO.getPhone());

		authOrderService.modifyState(authOrderPO);

		if (PayRspCodeEnum.SUCCESS.isValue(withoutVerifyYYContent.getResultCode())) {
			// 鉴权成功，则保存或更新用户鉴权信息
			saveUserAuthAndUserPayment(authOrderPO.getMerchantCode(), authOrderPO.getUserId(), params.getIdNo(), params.getName(),
					authOrderPO.getActPaymentCode(), params.getCardNo(), params.getPhone());
		}

		return withoutVerifyYYContent;
	}

	/**
	 * 发起鉴权
	 *
	 * @param authOrderPO
	 * @param params
	 * @return
	 * @throws Throwable
	 * @author buyi
	 * @date 2017-04-24 16:07:11
	 * @since v1.0.0
	 */
	public AuthenticationYYContent authentication(AuthOrderPO authOrderPO, AuthCounterSignParams params) throws Throwable {

		String idNo = StringUtils.isBlank(authOrderPO.getIdNoCip()) ? params.getIdNo() : CryptUtil.decrypt(authOrderPO.getIdNoCip());
		String name = StringUtils.isBlank(authOrderPO.getName()) ? params.getName() : authOrderPO.getName();
		String cardNo = StringUtils.isBlank(authOrderPO.getCardNoCip()) ? params.getCardNo() : CryptUtil.decrypt(authOrderPO.getCardNoCip());

		// 判断鉴权信息是否被占用
		userAuthService.checkIdNoAndName(authOrderPO.getMerchantCode(), authOrderPO.getUserId(), idNo, name);

		ThirdPayService adapterPayService = adapterService.adapterPayService(PaymentEnum.fromValue(params.getPaymentCode()));

		AuthenticationYYParams authenticationYYParams = new AuthenticationYYParams();
		BeanUtils.copyProperties(authOrderPO, authenticationYYParams);
		BeanUtils.copyProperties(params, authenticationYYParams);
		authenticationYYParams.setIdNo(idNo);
		authenticationYYParams.setCardNo(cardNo);
		authenticationYYParams.setName(name);

		AuthenticationYYContent authenticationYYContent = adapterPayService.authentication(authenticationYYParams);
		if (authenticationYYContent == null) {
			throw new YYException(PayRspCodeEnum.PAY_CODE_GET_AUTH_VERIFY_CODE_FAIL, "鉴权响应为空", "鉴权响应为空");
		}

		// 如果不是订单状态不是成功
		if (!PayRspCodeEnum.SUCCESS.isValue(authenticationYYContent.getResultCode())) {
			throw new YYException(authenticationYYContent.getResultCode(), authenticationYYContent.getResultMsg(),
					authenticationYYContent.getResultMsg());
		}

		// 鉴权成功,更新鉴权订单信息
		authOrderPO.setIdNo(DesensitizationUtil.convertIdCard(idNo));
		authOrderPO.setIdNoCip(CryptUtil.encrypt(idNo));
		authOrderPO.setIdType(IdCardTypeEnum.PRC_ID.getValue());
		authOrderPO.setName(name);
		authOrderPO.setCardNo(DesensitizationUtil.convertIdCard(cardNo));
		authOrderPO.setCardNoCip(CryptUtil.encrypt(cardNo));
		authOrderPO.setState(AuthStateEnum.SUCCESS.getValue());
		authOrderPO.setPhone(params.getPhone());

		authOrderService.modify(authOrderPO);

		// 保存用户鉴权信息
		saveUserAuthAndUserPayment(authOrderPO.getMerchantCode(), authOrderPO.getUserId(), idNo, name, authOrderPO.getActPaymentCode(), cardNo,
				params.getPhone());

		// 生成异步通知任务
		saveNotifyTask(authenticationYYContent, authOrderPO);

		return authenticationYYContent;
	}

	/**
	 * 保存异步通知消息
	 *
	 * @param authenticationYYContent
	 * @param authOrderPO
	 * @author buyi
	 * @date 2017-04-19 19:06:21
	 * @since v1.0.0
	 */
	private void saveNotifyTask(AuthenticationYYContent authenticationYYContent, AuthOrderPO authOrderPO) {
		try {
			// 获取商户信息,得到签名密钥
			MerchantConfigPO merchantConfigPO = merchantConfigService.queryByMerchantCode(authOrderPO.getMerchantCode());
			if (merchantConfigPO == null) {
				throw new YYException(PayRspCodeEnum.PAY_CODE_MERCHANT_NOT_EXISTS, "商户：" + authOrderPO.getMerchantCode() + "信息不存在");
			}

			AuthNotifyParams notifyParams = new AuthNotifyParams();
			notifyParams.setResultCode(authenticationYYContent.getResultCode());
			notifyParams.setResultMsg(authenticationYYContent.getResultMsg());
			notifyParams.setMerchantCode(authOrderPO.getMerchantCode());
			notifyParams.setOrderId(authOrderPO.getOrderId());
			notifyParams.setUserId(authOrderPO.getUserId());
			notifyParams.setPaymentCode(authOrderPO.getActPaymentCode());
			notifyParams.setName(authOrderPO.getName());
			notifyParams.setIdNo(CryptUtil.decrypt(authOrderPO.getIdNoCip()));
			notifyParams.setCardNo(CryptUtil.decrypt(authOrderPO.getCardNoCip()));

			AuthResultNotifyParams resultNotifyParams = new AuthResultNotifyParams();
			resultNotifyParams.setSign(notifyParams.sign(merchantConfigPO.getSignKey()));
			resultNotifyParams.setParams(notifyParams);

			// 保存异步通知任务

			payCommonService.saveNotifyTask(authOrderPO.getMerchantCode(), authOrderPO.getOrderId(), null, NotifyTaskTypeEnum.AUTHENTICATION,
					authOrderPO.getAuthOrderId(), authOrderPO.getNotifyUrl(), JacksonUtil.noemptyMapper.toJson(resultNotifyParams),
					DateUtil.getCurrentDateTime(), null, payConstants.getMaxNo(), null);

		} catch (Throwable e) {
			logger.error("鉴权保存异步通知异常", e);
		}

	}

	/**
	 * 保存用户鉴权信息
	 *
	 * @param merchantCode 商户编号
	 * @param userId 商户用户id
	 * @param idNo 身份证号
	 * @param name 姓名
	 * @param paymentCode 支付通道
	 * @param cardNo 银行卡
	 * @param phone 手机号
	 * @throws Throwable
	 * @author buyi
	 * @date 2017-04-24 16:26:54
	 * @since v1.0.0
	 */
	public void saveUserAuthAndUserPayment(String merchantCode, String userId, String idNo, String name, String paymentCode, String cardNo,
			String phone) throws Throwable {

		String idNoCip = CryptUtil.encrypt(idNo);

		QueryCardBinContent queryCardBin = null;
		try {
			queryCardBin = payCommonService.queryCardBin(merchantCode, cardNo);
		} catch (Exception e) {
			logger.error("保存鉴权信息，查询卡bin异常", e);
		}

		String bankCode = queryCardBin == null ? null : queryCardBin.getBankCode();
		String bankName = queryCardBin == null ? null : queryCardBin.getBankName();

		// 保存实名认证信息
		UserAuthPO userAuthPO = userAuthService.queryByUserIdAndMerchantCode(userId, merchantCode);
		try {
			if (userAuthPO == null) {
				userAuthPO = new UserAuthPO();
				userAuthPO.setMerchantCode(merchantCode);
				userAuthPO.setUserId(userId);
				userAuthPO.setIdNo(DesensitizationUtil.convertIdCard(idNo));
				userAuthPO.setIdNoCip(idNoCip);
				userAuthPO.setIdType(IdCardTypeEnum.PRC_ID.getValue());
				userAuthPO.setName(name);
				userAuthPO.setState(YesNoEnum.YES.getValue());
				userAuthService.saveAndReturnUserAuthId(userAuthPO);
			}
		} catch (DuplicateKeyException e) {
			// 判断身份证信息是否冲突
			logger.error("保存实名鉴权信息出现主键冲突,存在已经实名鉴权信息，需要运维跟踪问题,merchantCode:" + merchantCode + ",userId:" + userId);

			userAuthPO = userAuthService.queryByUserIdAndMerchantCode(userId, merchantCode);
			if (userAuthPO == null) {
				// 没有找相应商户的用户信息，则抛出异常
				logger.error(
						"保存实名鉴权信息出现主键冲突,存在已经实名鉴权信息,或者身份证已被使用，需要运维跟踪问题,merchantCode:" + merchantCode + ",userId:" + userId + ",idNoCip:" + idNoCip);
				return;
			}

			if (!StringUtils.equals(idNoCip, userAuthPO.getIdNoCip())) {
				// 如果实名信息存在，身份证号不一致，则异常
				logger.error(
						"保存实名鉴权信息出现主键冲突,存在已经实名鉴权信息,身份证不一致已被使用，需要运维跟踪问题,merchantCode:" + merchantCode + ",userId:" + userId + ",idNoCip:" + idNoCip);
				return;
			}
		}

		// 保存支付认证信息

		// 判断用户支付认证信息
		UserPaymentPO paymentPO = userPaymentService.query(merchantCode, userId, paymentCode);
		// 支付通道信息
		if (paymentPO != null && YesNoEnum.YES.isValue(paymentPO.getState())) {
			logger.info("商户：{}，用户：{}，支付通道：{}，存在有效的支付认证信息", merchantCode, userId, paymentCode);

			if (StringUtils.isBlank(paymentPO.getPhone()) && StringUtils.isNotBlank(phone)) {
				logger.info("商户：{}，用户：{}，支付通道：{}，存在有效的支付认证信息,手机号为空，更新手机号{}", merchantCode, userId, paymentCode, phone);
				userPaymentService.modifyPhone(paymentPO.getId(), phone);
			}

			return;
		}

		UserPaymentPO userPaymentPO = new UserPaymentPO();
		BeanUtils.copyProperties(userAuthPO, userPaymentPO);
		userPaymentPO.setUserAuthId(userAuthPO.getUserAuthId());
		userPaymentPO.setPaymentCode(paymentCode);
		userPaymentPO.setBankCode(bankCode);
		userPaymentPO.setBankName(bankName);
		userPaymentPO.setCardNo(DesensitizationUtil.convertBankCard(cardNo));
		userPaymentPO.setCardNoCip(CryptUtil.encrypt(cardNo));
		userPaymentPO.setPhone(phone);
		userPaymentPO.setState(YesNoEnum.YES.getValue());
		if (paymentPO == null) {
			try {
				userPaymentService.save(userPaymentPO);
			} catch (DuplicateKeyException e) {
				logger.error("保存支付鉴权信息出现主键冲突,存在支付鉴权信息，需要运维跟踪问题,merchantCode:" + merchantCode + ",userId:" + userId);
			}
		} else {
			userPaymentService.modify(userPaymentPO);
		}
	}

	public String notifyAuthOrder(NotifyTaskPO task) throws Exception {
		// 1.查询订单封装VO
		String rspJson = HttpUtil.post(task.getNotifyUrl(), task.getReqContent());
		if (StringUtils.isBlank(rspJson)) {
			logger.info("回调失败:{}", task.getOrderId());
		}

		return rspJson;
	}

	/**
	 * 保存鉴权订单
	 *
	 * @param params
	 * @throws Throwable
	 * @author buyi
	 * @date 2017-04-15 16:57:13
	 * @since v1.0.0
	 */
	public AuthOrderPO saveAuthOder(AuthOrderParams params) throws Throwable {
		// 判断重复下单
		AuthOrderPO orderPO = authOrderService.queryByOrderIdAndMerchantCode(params.getOrderId(), params.getMerchantCode());
		if (orderPO != null) {
			throw new YYException(PayRspCodeEnum.PAY_CODE_ORDER_DUPLICATE);
		}

		orderPO = new AuthOrderPO();
		BeanUtils.copyProperties(params, orderPO);

		// 支持银行卡、姓名、身份证号优先传参(姓名没有脱敏，直接跳过)
		if (StringUtils.isNotBlank(params.getCardNo())) {
			orderPO.setCardNo(DesensitizationUtil.convertIdCard(params.getCardNo()));
			orderPO.setCardNoCip(CryptUtil.encrypt(params.getCardNo()));
		}

		if (StringUtils.isNotBlank(params.getIdNo())) {
			orderPO.setIdNo(DesensitizationUtil.convertIdCard(params.getIdNo()));
			orderPO.setIdNoCip(CryptUtil.encrypt(params.getIdNo()));
			orderPO.setIdType(IdCardTypeEnum.PRC_ID.getValue());
		}

		if (StringUtils.isNotBlank(params.getCardNo())) {// 如果银行卡不为空
			QueryCardBinContent cardBin = payCommonService.queryCardBin(params.getMerchantCode(), params.getCardNo());
			String bankCode = cardBin == null ? null : cardBin.getBankCode();
			orderPO.setBankCode(bankCode);
		}

		PaymentEnum acPaymentEnum = routeService.routeAuthentication(params.getMerchantCode(), params.getPaymentCode());
		orderPO.setActPaymentCode(acPaymentEnum.getValue());

		orderPO.setState(AuthStateEnum.DEALING.getValue());

		authOrderService.saveAndReturnBusiKey(orderPO);

		return orderPO;
	}

	/**
	 * 独立鉴权-直连
	 *
	 * @param params
	 * @return
	 * @author xulqb
	 * @date 2017-12-22 9:53:01
	 * @since V1.0.0
	 */
	public AuthOrderPO saveAuthOderForWithout(AuthWithoutVerifyParams params) throws Throwable {
		AuthOrderPO orderPO = new AuthOrderPO();
		BeanUtils.copyProperties(params, orderPO);

		// 支持银行卡、姓名、身份证号优先传参(姓名没有脱敏，直接跳过)
		if (StringUtils.isNotBlank(params.getCardNo())) {
			orderPO.setCardNo(DesensitizationUtil.convertIdCard(params.getCardNo()));
			orderPO.setCardNoCip(CryptUtil.encrypt(params.getCardNo()));
		}

		if (StringUtils.isNotBlank(params.getIdNo())) {
			orderPO.setIdNo(DesensitizationUtil.convertIdCard(params.getIdNo()));
			orderPO.setIdNoCip(CryptUtil.encrypt(params.getIdNo()));
			orderPO.setIdType(IdCardTypeEnum.PRC_ID.getValue());
		}

		// 如果银行卡不为空
		if (StringUtils.isNotBlank(params.getCardNo())) {
			QueryCardBinContent cardBin = payCommonService.queryCardBin(params.getMerchantCode(), params.getCardNo());
			String bankCode = cardBin == null ? null : cardBin.getBankCode();
			orderPO.setBankCode(bankCode);
		}

		PaymentEnum acPaymentEnum = routeService.routeAuthentication(params.getMerchantCode(), params.getPaymentCode());
		orderPO.setActPaymentCode(acPaymentEnum.getValue());

		orderPO.setState(AuthStateEnum.INIT.getValue());

		//InetAddress.getLocalHost().getHostAddress()

		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
		String serverIp= RequestUtil.getIpAdr(request);
		orderPO.setServerIp(serverIp);

		// 唯一约束冲突标识位
		boolean duplicateKeyFlag = false;
		try {
			authOrderService.saveAndReturnBusiKey(orderPO);
		} catch (DuplicateKeyException e) {
			logger.error(Log.op("AuthService.saveAuthOderForWithout").msg("唯一约束冲突").kv("params", params).toString(), e);
			duplicateKeyFlag = true;
		}

		if (duplicateKeyFlag) {
			orderPO = authOrderService.queryByOrderIdAndMerchantCode(params.getOrderId(), params.getMerchantCode());
			// 插入失败,报唯一约束冲突异常,没有查到信息，向上层报系统异常
			if (orderPO == null) {
				throw new YYException(PayRspCodeEnum.COMMON_ERROR_OBJECT_NOT_FOUND, "鉴权订单不存在", "鉴权订单不存在");
			}
		}

		return orderPO;
	}

	/**
	 * 鉴权信息转换
	 *
	 * @param params
	 * @return
	 * @author xulqb
	 * @date 2017-12-21 13:59:01
	 * @since V1.0.0
	 */
	public AuthOrderPO transferAuthOder(AuthWithoutVerifyDirectParams params) throws Throwable {
		AuthOrderPO orderPO = new AuthOrderPO();
		BeanUtils.copyProperties(params, orderPO);
		return orderPO;
	}

	/**
	 * 判断用户认证信息是否存在
	 *
	 * @param authParams
	 * @return
	 * @author xulqb
	 * @date 2017-12-21 17:44:01
	 * @since V1.0.0
	 */
	public void checkUserAuth(AuthWithoutVerifyParams authParams) throws Throwable {
		logger.info(Log.op("AuthService.checkUserAuth").msg("判断用户认证信息是否存在").kv("authParams", authParams).toString());
		userAuthService.checkIdNoAndName(authParams.getMerchantCode(), authParams.getUserId(), authParams.getIdNo(), authParams.getName());
	}

}
